#ifndef __WIZ_BASE_RTTI_HPP__SHANHAOBO_19800429__
#define __WIZ_BASE_RTTI_HPP__SHANHAOBO_19800429__

#include "./Core/WizBaseCoreDeclare.hpp"
#include "./WizBaseAssert.hpp"

namespace Wiz
{
    namespace RTTI
    {
        //////////////////////////////////////////////////////////////////////////
        namespace Core
        {
            template<class BaseT = ::Wiz::Null::Type>
            class Type : public BaseT
            {
            protected:
                typedef Type tCoreRTTI;

				WIZ_DECLARE_PTR_WITHNAME(Type, tCore); 
			protected:
				Type() : m_SuperRTTI(WIZ_NULLPTR)
				{
				}
            public:
                Type(tCoreFixedConstPtr BaseRTTI) : m_SuperRTTI(BaseRTTI)
                {
                }
            public:
                static tCoreFixedConstPtr GetMyRTTI()
                {
                    return WIZ_NULLPTR;
                }
                tCoreFixedConstPtr GetSuperRTTI() const
                {
                    return m_SuperRTTI;
                }
                virtual tCoreFixedConstPtr GetRealRTTI() const
                {
                    return GetMyRTTI();
                }
            protected:
                tCoreFixedConstPtr   m_SuperRTTI;
            };
        } /// end of namespace Core
        //////////////////////////////////////////////////////////////////////////
		template<class DerivedT, class BaseT>
        class Type : public BaseT
        {
        protected:
            typedef typename BaseT::tCoreConstPtr       tCoreConstPtr;
            typedef typename BaseT::tCoreFixedConstPtr  tCoreFixedConstPtr;
            typedef typename BaseT::tCoreRTTI           tCoreRTTI;
        public:
            Type()
            {}
		public:
            static tCoreFixedConstPtr GetMyRTTI()
            {
                static tCoreRTTI s_RTTI(BaseT::GetMyRTTI());
                return &s_RTTI;
            }
            virtual tCoreFixedConstPtr GetRealRTTI() const
            {
                return DerivedT::GetMyRTTI();
			}
		protected:
			/// Tests if this class is derived from a specific class(or is that type itself);
			::Wiz::Bool::Type IsDerivedFromOrItself(tCoreFixedConstPtr SuperRTTIPtr) const
			{
				WIZ_ASSERT(::Wiz::IsValidPtr(GetRealRTTI()));
				WIZ_ASSERT(::Wiz::IsValidPtr(SuperRTTIPtr));

				tCoreConstPtr thisRTTIPtr = GetRealRTTI();
				while (thisRTTIPtr != SuperRTTIPtr)
				{
					thisRTTIPtr = thisRTTIPtr->GetSuperRTTI();
					if (::Wiz::NotValidPtr(thisRTTIPtr))
					{
						return ::Wiz::Bool::False;
					}
				}

				return ::Wiz::Bool::True;
			}
        public:
            ::Wiz::Bool::Type IsKindOf(tCoreFixedConstPtr OtherPtr) const
            {
                WIZ_ASSERT(::Wiz::IsValidPtr(GetRealRTTI()));
                WIZ_ASSERT(::Wiz::IsValidPtr(OtherPtr->GetRealRTTI()));

                return IsDerivedFromOrItself(OtherPtr->GetRealRTTI());
            }

            template<class U>
            ::Wiz::Bool::Type IsKindOf() const
            {
                WIZ_ASSERT(::Wiz::IsValidPtr(GetRealRTTI()));
                WIZ_ASSERT(::Wiz::IsValidPtr(U::GetMyRTTI()));

				return IsDerivedFromOrItself(U::GetMyRTTI());
            }

            /// Tests if this class is a specific type.
            ::Wiz::Bool::Type IsA(tCoreFixedConstPtr OtherPtr) const
            {
                WIZ_ASSERT(::Wiz::IsValidPtr(GetRealRTTI()));
                WIZ_ASSERT(::Wiz::IsValidPtr(OtherPtr->GetRealRTTI()));

                return OtherPtr->GetRealRTTI() == GetRealRTTI();
            }

            template<class U>
            ::Wiz::Bool::Type IsA() const
            {
                WIZ_ASSERT(::Wiz::IsValidPtr(GetRealRTTI()));
                WIZ_ASSERT(::Wiz::IsValidPtr(U::GetMyRTTI()));

                return U::GetMyRTTI() == GetRealRTTI();
            }
        };

        //////////////////////////////////////////////////////////////////////////
        template<class BaseT = ::Wiz::Null::Type>
        class BaseType : public ::Wiz::RTTI::Type<BaseType<BaseT>, ::Wiz::RTTI::Core::Type<BaseT> >
        {
        public:
            BaseType()
            {}
        };
        //////////////////////////////////////////////////////////////////////////
    } /// end of namespace RTTI
} /// end of namespace Wiz

#endif /*__WIZ_BASE_RTTI_HPP__SHANHAOBO_19800429__*/
